"""EDA主处理管道

统一的EDA信号处理流水线，协调预处理、峰值检测、指标计算和质量评估等步骤。
支持灵活的算法配置和错误处理机制。
"""

import numpy as np
import time
import logging
from typing import Dict, Any, Optional, Union
from ..core.registry import get_algorithm

# 配置日志
logger = logging.getLogger(__name__)

def process_eda_pipeline(
    eda_data: Union[np.ndarray, list], 
    config: Optional[Dict[str, str]] = None, 
    sampling_rate: float = 4.0
) -> Dict[str, Any]:
    """
    统一的EDA处理管道
    
    Args:
        eda_data: EDA信号数据（numpy数组或列表）
        config: 算法配置字典，包含各步骤使用的算法名称
        sampling_rate: 采样率（Hz）
    
    Returns:
        处理结果字典，包含：
        - success: 处理是否成功
        - error: 错误信息（如果有）
        - config: 使用的算法配置
        - metrics: 计算得到的指标
        - quality: 质量评估结果
        - processing_info: 处理过程信息
        - raw_data: 原始数据信息
        - processed_data: 处理后的数据（可选）
    
    Example:
        >>> import numpy as np
        >>> data = np.random.normal(5, 1, 1000)
        >>> result = process_eda_pipeline(data, sampling_rate=4)
        >>> print(f"质量评分: {result['quality']['quality_score']}")
    """
    # 记录开始时间
    start_time = time.time()
    
    # 默认配置
    default_config = {
        'preprocessor': 'improved',
        'peak_detector': 'improved', 
        'metrics_calculator': 'comprehensive',
        'quality_assessor': 'improved'
    }
    
    # 合并用户配置
    if config:
        default_config.update(config)
    config = default_config
    
    # 初始化结果字典
    result = {
        'success': False,
        'error': None,
        'config': config,
        'metrics': {},
        'quality': {},
        'processing_info': {},
        'raw_data': {},
        'processed_data': None
    }
    
    try:
        # 数据验证和预处理
        eda_data = _validate_and_prepare_data(eda_data)
        if eda_data is None:
            result['error'] = "输入数据无效或为空"
            return result
        
        # 记录原始数据信息
        result['raw_data'] = {
            'length': len(eda_data),
            'duration_seconds': len(eda_data) / sampling_rate,
            'duration_minutes': len(eda_data) / sampling_rate / 60,
            'sampling_rate': sampling_rate,
            'mean_value': float(np.mean(eda_data)),
            'std_value': float(np.std(eda_data)),
            'min_value': float(np.min(eda_data)),
            'max_value': float(np.max(eda_data))
        }
        
        logger.info(f"开始处理EDA数据，长度: {len(eda_data)}, 采样率: {sampling_rate}Hz")
        
        # 步骤1: 预处理
        logger.debug(f"执行预处理算法: {config['preprocessor']}")
        preprocessor = get_algorithm('preprocessors', config['preprocessor'])
        processed_data = preprocessor(eda_data, sampling_rate)
        
        if processed_data is None or 'filtered' not in processed_data:
            result['error'] = "预处理失败：未返回有效的处理结果"
            return result
        
        # 步骤2: 峰值检测
        logger.debug(f"执行峰值检测算法: {config['peak_detector']}")
        peak_detector = get_algorithm('peak_detectors', config['peak_detector'])
        peaks, properties = peak_detector(processed_data['filtered'], sampling_rate)
        
        if peaks is None:
            peaks = np.array([])
            properties = {'peak_heights': np.array([]), 'widths': np.array([])}
            logger.warning("峰值检测未找到任何峰值")
        
        # 步骤3: 指标计算
        logger.debug(f"执行指标计算算法: {config['metrics_calculator']}")
        metrics_calculator = get_algorithm('metrics_calculators', config['metrics_calculator'])
        metrics = metrics_calculator(processed_data['filtered'], peaks, properties, sampling_rate)
        
        if not metrics:
            logger.warning("指标计算返回空结果")
            metrics = {}
        
        # 步骤4: 质量评估
        logger.debug(f"执行质量评估算法: {config['quality_assessor']}")
        quality_assessor = get_algorithm('quality_assessors', config['quality_assessor'])
        # 使用统一的参数接口调用质量评估算法
        quality_result = quality_assessor(
            eda_signal=eda_data,
            sampling_rate=sampling_rate,
            peaks=peaks,
            processed_data=processed_data
        )
        
        # 处理质量评估返回值（元组格式：score, quality_report）
        if isinstance(quality_result, tuple) and len(quality_result) == 2:
            quality_score, quality = quality_result
            # 确保quality_score在quality字典中
            if isinstance(quality, dict):
                quality['quality_score'] = quality_score
        else:
            # 兼容旧格式
            quality = quality_result if quality_result else {}
        
        if not quality:
            logger.warning("质量评估返回空结果")
            quality = {}
        
        # 计算处理时间
        processing_time = time.time() - start_time
        
        # 汇总处理信息
        processing_info = {
            'data_points': len(eda_data),
            'duration_min': len(eda_data) / sampling_rate / 60,
            'detected_peaks': len(peaks),
            'algorithm_used': config,
            'processing_time_seconds': round(processing_time, 3),
            'peaks_per_minute': len(peaks) / (len(eda_data) / sampling_rate / 60) if len(eda_data) > 0 else 0,
            'data_quality_flags': _generate_quality_flags(eda_data, processed_data, quality)
        }
        
        # 更新结果
        result.update({
            'success': True,
            'metrics': metrics,
            'quality': quality,
            'processing_info': processing_info,
            'processed_data': {
                'peaks': peaks.tolist() if isinstance(peaks, np.ndarray) else peaks,
                'peak_properties': {
                    k: v.tolist() if isinstance(v, np.ndarray) else v 
                    for k, v in properties.items()
                }
            }
        })
        
        logger.info(f"EDA处理完成，用时: {processing_time:.3f}秒，检测到 {len(peaks)} 个峰值")
        
    except Exception as e:
        error_msg = f"EDA处理管道出错: {str(e)}"
        logger.error(error_msg, exc_info=True)
        result['error'] = error_msg
        result['processing_info']['processing_time_seconds'] = time.time() - start_time
    
    return result

def _validate_and_prepare_data(eda_data: Union[np.ndarray, list]) -> Optional[np.ndarray]:
    """验证和准备输入数据
    
    Args:
        eda_data: 输入的EDA数据
        
    Returns:
        验证后的numpy数组，如果数据无效则返回None
    """
    try:
        # 转换为numpy数组
        if isinstance(eda_data, list):
            eda_data = np.array(eda_data)
        elif not isinstance(eda_data, np.ndarray):
            logger.error(f"不支持的数据类型: {type(eda_data)}")
            return None
        
        # 检查数据长度
        if len(eda_data) == 0:
            logger.error("输入数据为空")
            return None
        
        if len(eda_data) < 10:
            logger.warning(f"数据长度过短: {len(eda_data)}，可能影响分析结果")
        
        # 检查数据类型
        if not np.issubdtype(eda_data.dtype, np.number):
            logger.error(f"数据必须为数值类型，当前类型: {eda_data.dtype}")
            return None
        
        # 处理无穷大和NaN值
        if np.any(np.isinf(eda_data)):
            logger.warning("检测到无穷大值，将被替换为NaN")
            eda_data = np.where(np.isinf(eda_data), np.nan, eda_data)
        
        # 检查NaN比例
        nan_ratio = np.sum(np.isnan(eda_data)) / len(eda_data)
        if nan_ratio > 0.5:
            logger.error(f"NaN值比例过高: {nan_ratio:.2%}")
            return None
        elif nan_ratio > 0.1:
            logger.warning(f"检测到较多NaN值: {nan_ratio:.2%}")
        
        # 检查数据范围
        valid_data = eda_data[~np.isnan(eda_data)]
        if len(valid_data) > 0:
            if np.min(valid_data) < -10 or np.max(valid_data) > 100:
                logger.warning(f"数据范围异常: [{np.min(valid_data):.3f}, {np.max(valid_data):.3f}]")
        
        return eda_data.astype(np.float64)
        
    except Exception as e:
        logger.error(f"数据验证失败: {str(e)}")
        return None

def _generate_quality_flags(eda_data: np.ndarray, processed_data: Dict, quality: Dict) -> Dict[str, bool]:
    """生成数据质量标志
    
    Args:
        eda_data: 原始EDA数据
        processed_data: 处理后的数据
        quality: 质量评估结果
        
    Returns:
        质量标志字典
    """
    flags = {}
    
    try:
        # 检查零值比例
        zero_ratio = quality.get('zero_ratio_percent', 0)
        flags['high_zero_ratio'] = zero_ratio > 10
        
        # 检查信噪比
        snr = quality.get('snr_db', 0)
        flags['low_snr'] = snr < 10
        
        # 检查质量评分
        quality_score = quality.get('quality_score', 0)
        flags['low_quality'] = quality_score < 50
        
        # 检查数据长度
        flags['short_duration'] = len(eda_data) < 240  # 少于1分钟（4Hz采样）
        
        # 检查NaN值
        nan_ratio = np.sum(np.isnan(eda_data)) / len(eda_data)
        flags['high_nan_ratio'] = nan_ratio > 0.1
        
    except Exception as e:
        logger.warning(f"生成质量标志时出错: {str(e)}")
        flags['quality_check_failed'] = True
    
    return flags


class EDAProcessor:
    """
    EDA信号处理器类
    
    提供面向对象的EDA信号处理接口，封装了完整的处理流水线。
    支持自定义配置和批量处理。
    
    Attributes:
        config: 算法配置字典
        default_sampling_rate: 默认采样率
    
    Example:
        >>> processor = EDAProcessor()
        >>> result = processor.process(eda_data, sampling_rate=4.0)
        >>> print(f"检测到 {len(result['peaks']['peak_indices'])} 个峰值")
    """
    
    def __init__(self, config: Optional[Dict[str, Any]] = None):
        """
        初始化EDA处理器
        
        Args:
            config: 算法配置字典，可包含以下键：
                - preprocessing: 预处理配置
                - peak_detection: 峰值检测配置  
                - metrics: 指标计算配置
                - quality: 质量评估配置
        """
        self.config = config or {}
        self.default_sampling_rate = 4.0
        
        # 设置默认算法配置
        self._setup_default_config()
        
        logger.info("EDA处理器初始化完成")
    
    def _setup_default_config(self):
        """设置默认算法配置"""
        default_algorithms = {
            'preprocessor': 'improved',
            'peak_detector': 'improved', 
            'metrics_calculator': 'comprehensive',
            'quality_assessor': 'improved'
        }
        
        # 从用户配置中提取算法选择
        if 'preprocessing' in self.config:
            if 'algorithm' in self.config['preprocessing']:
                default_algorithms['preprocessor'] = self.config['preprocessing']['algorithm']
        
        if 'peak_detection' in self.config:
            if 'algorithm' in self.config['peak_detection']:
                default_algorithms['peak_detector'] = self.config['peak_detection']['algorithm']
        
        if 'metrics' in self.config:
            if 'algorithm' in self.config['metrics']:
                default_algorithms['metrics_calculator'] = self.config['metrics']['algorithm']
        
        if 'quality' in self.config:
            if 'algorithm' in self.config['quality']:
                default_algorithms['quality_assessor'] = self.config['quality']['algorithm']
        
        self.algorithm_config = default_algorithms
    
    def process(self, eda_data: Union[np.ndarray, list], 
                sampling_rate: Optional[float] = None) -> Dict[str, Any]:
        """
        处理EDA信号数据
        
        Args:
            eda_data: EDA信号数据
            sampling_rate: 采样率（Hz），如果未提供则使用默认值
        
        Returns:
            处理结果字典，包含处理后的信号、峰值、指标和质量评估
        """
        if sampling_rate is None:
            sampling_rate = self.default_sampling_rate
        
        logger.info(f"开始处理EDA数据，采样率: {sampling_rate}Hz")
        
        # 调用主处理管道
        result = process_eda_pipeline(
            eda_data=eda_data,
            config=self.algorithm_config,
            sampling_rate=sampling_rate
        )
        
        # 重新组织结果格式以匹配预期的接口
        if result['success']:
            formatted_result = {
                'processed_signal': result.get('processed_data', {}).get('filtered', eda_data),
                'peaks': {
                    'peak_indices': result.get('metrics', {}).get('peak_indices', []),
                    'peak_amplitudes': result.get('metrics', {}).get('peak_amplitudes', []),
                    'peak_count': result.get('metrics', {}).get('scr_count', 0)
                },
                'metrics': result.get('metrics', {}),
                'quality': {
                    'overall_score': result.get('quality', {}).get('quality_score', 0),
                    'snr': result.get('quality', {}).get('snr', 0),
                    'artifacts': result.get('quality', {}).get('artifact_ratio', 0),
                    'details': result.get('quality', {})
                },
                'processing_info': result.get('processing_info', {}),
                'raw_data_info': result.get('raw_data', {})
            }
            return formatted_result
        else:
            # 处理失败时返回错误信息
            raise RuntimeError(f"EDA处理失败: {result.get('error', '未知错误')}")
    
    def process_step_by_step(self, eda_data: Union[np.ndarray, list], 
                           sampling_rate: Optional[float] = None) -> Dict[str, Any]:
        """
        分步骤处理EDA信号，返回每个步骤的结果
        
        Args:
            eda_data: EDA信号数据
            sampling_rate: 采样率（Hz）
        
        Returns:
            包含每个处理步骤结果的字典
        """
        if sampling_rate is None:
            sampling_rate = self.default_sampling_rate
        
        logger.info("开始分步骤处理EDA数据")
        
        # 数据验证
        eda_data = _validate_and_prepare_data(eda_data)
        if eda_data is None:
            raise ValueError("输入数据无效或为空")
        
        results = {
            'original_data': eda_data,
            'sampling_rate': sampling_rate
        }
        
        try:
            # 步骤1: 预处理
            preprocessor = get_algorithm('preprocessors', self.algorithm_config['preprocessor'])
            processed_data = preprocessor(eda_data, sampling_rate)
            results['preprocessing'] = processed_data
            
            # 步骤2: 峰值检测
            peak_detector = get_algorithm('peak_detectors', self.algorithm_config['peak_detector'])
            filtered_signal = processed_data.get('filtered', eda_data)
            peak_data = peak_detector(filtered_signal, sampling_rate)
            results['peak_detection'] = peak_data
            
            # 步骤3: 指标计算
            metrics_calculator = get_algorithm('metrics_calculators', self.algorithm_config['metrics_calculator'])
            metrics = metrics_calculator(filtered_signal, peak_data, sampling_rate)
            results['metrics'] = metrics
            
            # 步骤4: 质量评估
            quality_assessor = get_algorithm('quality_assessors', self.algorithm_config['quality_assessor'])
            # 使用统一的参数接口调用质量评估算法
            quality_result = quality_assessor(
                eda_signal=eda_data,
                sampling_rate=sampling_rate,
                peaks=peak_data,
                processed_data={'filtered': filtered_signal}
            )
            
            # 处理质量评估返回值（元组格式：score, quality_report）
            if isinstance(quality_result, tuple) and len(quality_result) == 2:
                quality_score, quality = quality_result
                # 确保quality_score在quality字典中
                if isinstance(quality, dict):
                    quality['quality_score'] = quality_score
            else:
                # 兼容旧格式
                quality = quality_result if quality_result else {}
            
            results['quality'] = quality
            
            logger.info("分步骤处理完成")
            return results
            
        except Exception as e:
            logger.error(f"分步骤处理失败: {str(e)}")
            raise RuntimeError(f"分步骤处理失败: {str(e)}")
    
    def get_config(self) -> Dict[str, Any]:
        """获取当前配置"""
        return {
            'user_config': self.config,
            'algorithm_config': self.algorithm_config,
            'default_sampling_rate': self.default_sampling_rate
        }
    
    def update_config(self, new_config: Dict[str, Any]):
        """更新配置"""
        self.config.update(new_config)
        self._setup_default_config()
        logger.info("配置已更新")
    
    def __repr__(self) -> str:
        """字符串表示"""
        return f"EDAProcessor(algorithms={self.algorithm_config})"